<h1>How to cache your AOP configuration</h1>

<p>
    During the last sections, we have progressively introduced the main concepts
    behind this simple and useful paradigm. But with the introduction of the
    annotation configuration, you might have become a bit sceptical about the
    performances of the container builder. In fact, at each request, all the
    aspect classes are scanned wether it is needed or not: here you can see how
    to cache your <b>AOP</b> configuration so that the initialization is dumped
    and executed only when needed.
</p>

<p>
    Let's see how we used to initialize our aspect container:
</p>

<div class="code">
    <code>
        $aspectContainer = new aspectContainerBuilder('FooAspect');<br />
    </code>
</div>

<p>
    Ok, <b>Aspect PHP</b> comes bundle with a <b>PHP</b> dumper class:
    <i>aspectContainerDumper</i>. This class implements the method
    <code>dump($className)</code> which takes the name of the class to generate
    as a parameter and returns the generated <b>PHP</b> code as a string:
</p>

<div class="code">
    <code>
        $aspectContainer = new aspectContainerBuilder('FooAspect');<br />
        <br />
        $dumper = new aspectContainerDumper($aspectContainer);<br />
        $code = $dumper->dump('myAspectContainer');<br />
        <br />
        file_put_contents(dirname(__FILE__) . '/somewhere/container.php', $code);<br />
    </code>
</div>

<p>
    Now you should have something which looks like this in your
    <code>/somewhere/container.php</code> file:
</p>

<div class="code">
    <code>
        class myAspectContainer extends aspectContainerBuilder {<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;public function __construct() {<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (isset(self::$instance)) {<br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new LogicException('Cannot instantiate two aspect containers!');<br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self::$instance = $this;<br />
        &nbsp;&nbsp;&nbsp;&nbsp;}<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;public static function getInstance() {<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (isset(self::$instance)) {<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!isset($this->aroundPointcuts)) {<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this->aroundPointcuts = array(<br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this->beforePointcuts = array(<br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new aspectPointcut('FooAspect', 'myBeforeAdvice', false, '/^Foo->do.*$/', array())<br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this->afterReturningPointcuts = array(<br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this->afterThrowingPointcuts = array(<br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return self::$instance;<br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new RuntimeException('No aspect container instanciated!');<br />
        &nbsp;&nbsp;&nbsp;&nbsp;}<br />
        <br />
        }<br />
    </code>
</div>

<p class="notice">
    The code itself isn't really interesting but you might have noticed that the
    created class extends <i>aspectContainerBuilder</i> but never calls for the
    parent constructor. So nothing is scanned and all the pointcuts are dumped
    in the <code>getInstance()</code> method!
</p>

<p>
    Now let's take a look at how to integrate this feature to projects with at
    least two different environments: the <b>debug</b> environment where the
    <b>AOP</b> configuration is checked every times for changes and the
    <b>release</b> environment where the configuration is cached during the
    first request and never scanned again (which means the cache needs to be
    cleaned up after every changes!):
</p>

<div class="code">
    <code>
        require_once dirname(__FILE__) . '/path/to/lib/aspectAutoloader.php';<br />
        aspectAutoloader::register();<br />
        <br />
        require_once dirname(__FILE__) . '/Foo.class.php';<br />
        require_once dirname(__FILE__) . '/FooAspect.class.php';<br />
        <br />
        $name = 'myProjectAspectContainer';<br />
        $file = sys_get_temp_dir() . '/' . $name . '.php';<br />
        <br />
        if (!$isDebug && file_exists($file)) {<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;require_once $file;<br />
        &nbsp;&nbsp;&nbsp;&nbsp;$aspectContainer = new $name();<br />
        <br />
        } else {<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;<b>// Builds up the aspect container dynamically</b><br />
        &nbsp;&nbsp;&nbsp;&nbsp;$aspectContainer = new aspectContainerBuilder('FooAspect');<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;if (!$isDebug) {<br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$dumper = new aspectContainerDumper($aspectContainer);<br />
        <br />
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file_put_contents($file, $dumper->dump($name));<br />
        &nbsp;&nbsp;&nbsp;&nbsp;}<br />
        <br />
        }<br />
        <br />
        $foo = new aspectProxy(new Foo());<br />
        $foo->doSomeStuff('AOP');<br />
    </code>
</div>

<p>
    That's all for this library! The next section includes tips on how to
    integrate <b>Aspect PHP</b> in a <b>Symfony</b> project and some useful
    hacks about dependency injection.
</p>